;
; SYSLIB Module Name:  SZCPR
; Author:  Richard Conn
; SYSLIB Version Number:  2.0
; Module Version Number:  1.0
; Module Entry Points:
;	ZINIMC		ZINIEXT		ZCPRSET		ZCPRQ
;	ZMCPTR		ZPFIND		ZFSTAT
; Module External References:
;	BDOS
;

;
;	THIS MODULE CONTAINS SEVERAL ROUTINES WHICH ARE SPECIFICALLY
; DESIGNED TO SUPPORT APPLICATION WITH FEATURES OF THE NEW ZCPR2 COMMAND
; PROCESSOR REPLACEMENT.
;

;
;  DEFAULT VALUES FOR SPECIAL FLAGS/ADDRESSES
;
CURSET	EQU	'$'	; CURRENT USER OR DISK INDICATOR
DMASET	EQU	80H	; ADDRESS OF DMA BUFFER

;
;  EXTERNALS
;
	EXT	BDOS

;
;  ZINIMC -- THIS ROUTINE MUST BE CALLED BEFORE THE ZMCPTR ROUTINE
;	IN THIS PACKAGE.  IT DEFINES THE BASE ADDRESS OF THE MULTIPLE
;	COMMAND LINE BUFFER IN THE USER'S ZCPR2 SYSTEM
;		HL - POINTER TO BASE ADDRESS OF MULTIPLE COMMAND LINE BUFFER
;
ZINIMC::
	PUSH	PSW
	MVI	A,0FFH	; SAY THAT MULTIPLE COMMANDS ARE DEFINED
	STA	MCFLG	; SET MULTIPLE COMMAND FLAG
	SHLD	MCADR	; SAVE ADDRESS
	POP	PSW
	RET

;
;  ZINIEXT -- THIS ROUTINE DEFINES THE BASE ADDRESS OF THE USER'S EXTERNAL
;	PATH EXPRESSING IN THE USER'S ZCPR2 SYSTEM
;		HL - POINTER TO BASE ADDRESS OF EXTERNAL PATH EXPRESSION
;	THIS ROUTINE DOES NOT HAVE TO BE CALLED BY THE USER IF HE HAS NO
;	EXTERNAL PATHS; A NULL PATH IS ASSUMED IF THIS ROUTINE IS NOT
;	CALLED
;
ZINIEXT::
	SHLD	EXTADR	; SAVE ADDRESS
	RET

;
;  ZCPRSET -- SET IMPORTANT SYSTEM VALUES FOR ZCPR-ORIENTED ROUTINES
;	ON ENTRY, A=CHAR THAT INDICATES CURRENT USER OR DISK ($ RECOMMENDED)
;		HL = ADDRESS OF DMA BUFFER (80H RECOMMENDED)
;	THIS ROUTINE NEED BE CALLED ONLY IF THE USER'S VALUES ARE
;		DIFFERENT FROM THE RECOMMENDED VALUES
;
ZCPRSET::
	STA	CURIND	; SET INDICATOR
	SHLD	DMADR	; SET DMA ADDRESS
	RET
CURIND:
	DB	CURSET	; SET RECOMMENDED VALUE
DMADR:
	DW	DMASET	; SET RECOMMENDED VALUE

;
;  ZCPRQ -- QUESTION ZCPR ROUTINE STATUS; RETURNS:
;	HL = EXTERNAL PATH ADDRESS
;	DE = MULTIPLE COMMAND ADDRESS
;	A = MULTIPLE COMMAND AVAILABLE FLAG (0=NO)
;
ZCPRQ::
	LHLD	MCADR	; GET MULTIPLE COMMAND ADDRESS
	XCHG		; ... IN DE
	LHLD	EXTADR	; GET EXTERNAL PATH ADDRESS
	LDA	MCFLG	; GET MC FLAG
	RET

;
;  GENERAL-PURPOSE BUFFERS
;
NOPATH:
	DB	0	; EMPTY PATH
MCFLG:
	DB	0	; 0 SAYS NO MULTIPLE COMMAND LINE BUFFER
MCADR:
	DS	2	; ADDRESS OF MULTIPLE COMMAND LINE IF AVAILABLE
EXTADR:
	DW	NOPATH	; ADDRESS OF EXTERNAL PATH (ASSUME NO PATH)
CDISK:
	DS	1	; CURRENT DISK NUMBER
CUSER:
	DS	1	; CURRENT USER NUMBER
TDISK:
	DS	1	; TEMP DISK NUMBER
TUSER:
	DS	1	; TEMP USER NUMBER

;
;  MCPTR -- RETURN WITH HL POINTING TO NEXT BYTE OF COMMAND LINE
;	IF MULTIPLE COMMANDS ARE ENABLED
;	A IS RETURN CODE; A=0 AND ZERO FLAG SET (Z) IF ERROR,
;		A=0FFH AND ZERO FLAG CLEAR (NZ) IF NO ERROR
;
ZMCPTR::
	LHLD	MCADR	; GET ADDRESS OF MULTIPLE COMMAND LINE
	MOV	A,M	; GET LOW-ORDER
	INX	H	; PT TO HIGH-ORDER
	MOV	H,M	; GET HIGH-ORDER
	MOV	L,A	; SET LOW-ORDER
	LDA	MCFLG	; MULTIPLE COMMANDS AVAILABLE?
	ORA	A	; 0=NO
	RET

;
;  PFIND -- LOOK FOR FILE WHOSE FCB IS PTED TO BY DE ALONG PATH
;	IF FILE FOUND, RETURN DISK NUMBER IN B, USER NUMBER IN C, AND
;	ZERO FLAG SET (Z) WITH A=0FFH; IF NOT FOUND, RETURN WITH ZERO FLAG
;	SET (Z) AND A=0; IF ERROR, RETURN WITH ERROR CODE (1,2,3) AND NZ
;
;	INPUTS:  DE PTS TO FCB, B IS FLAG: B=0 IF NO CURRENT SEARCH ALSO,
;						<>0 IF CURRENT SEARCH
;	OUTPUTS:  B=DISK, C=USER IF FOUND
;			ZERO FLAG SET (Z) IF NOT FOUND
;			ZERO FLAG CLEAR (NZ) IF FOUND
;
ZPFIND::
	PUSH	H	; SAVE REGS
	PUSH	D
	PUSH	D	; SAVE FCB PTR
	XRA	A	; SET DISK NUMBER TO CURRENT
	STAX	D	; CHANGE FCB
	MVI	C,25	; GET CURRENT DISK
	CALL	BDOSH
	STA	CDISK	; SAVE CURRENT DISK
	STA	TDISK	; SET TEMP DISK
	MVI	C,32	; GET CURRENT USER
	MVI	E,0FFH
	CALL	BDOSH
	STA	CUSER	; SAVE CURRENT USER
	STA	TUSER	; SAVE TEMP USER
	POP	D	; GET FCB PTR
	LHLD	EXTADR	; GET ADDRESS OF EXTERNAL PATH
	MOV	A,B	; SEARCH CURRENT?
	ORA	A	; 0=NO
	JZ	PF1
	MVI	C,17	; SEARCH FOR FIRST
	CALL	BDOSH
	INR	A	; FILE FOUND?
	JNZ	PFFND
PF1:
	MOV	A,M	; GET DRIVE NUMBER FROM PATH
	ORA	A	; 0=DONE=FILE NOT FOUND
	JZ	PFNFND
	LDA	CURIND	; GET CURRENT INDICATOR
	CMP	M	; CURRENT DISK?
	MOV	A,M	; RESTORE DISK NUMBER
	JNZ	PF2
	LDA	CDISK	; GET CURRENT DISK
	INR	A	; INCREMENT FOR LATER DECREMENT
PF2:
	PUSH	D	; SAVE FCB PTR
	DCR	A	; ADJUST TO 0-15
	ANI	0FH	; MASK FOR DISK NUMBER
	STA	TDISK	; SET TEMP DISK
	MOV	E,A	; DISK NUMBER IN E
	MVI	C,14	; SELECT DISK
	CALL	BDOSH
	INX	H	; PT TO USER NUMBER
	MOV	A,M	; GET USER NUMBER
	ANI	7FH	; MASK OUT SYSTEM FLAG
	MOV	B,A	; SAVE IN B
	LDA	CURIND	; CURRENT USER?
	CMP	B
	MOV	A,B	; GET CURRENT USER BACK
	JNZ	PF3
	LDA	CUSER	; GET CURRENT USER
PF3:
	STA	TUSER	; SET TEMP USER
	MOV	E,A	; USER NUMBER IN E
	MVI	C,32	; SELECT USER
	CALL	BDOSH
	POP	D	; GET PTR TO FCB
	INX	H	; PT TO NEXT PATH ENTRY
	MVI	C,17	; NOW, SEARCH FOR FILE
	CALL	BDOSH
	INR	A	; FILE FOUND?
	JZ	PF1	; CONTINUE SEARCH IF NOT FOUND
;
;  FILE FOUND FLAG SETTING
;
PFFND:
	MVI	A,0FFH	; FOUND RETURN CODE
	ORA	A	; SET FLAGS
	JMP	FNDEXIT
;
;  FILE NOT FOUND ERROR
;
PFNFND:
	XRA	A	; FILE NOT FOUND
FNDEXIT:
	PUSH	PSW	; SAVE RETURN CODE
	LDA	CDISK	; RESTORE CURRENT DISK
	MOV	E,A	; SAVE IN E
	LDA	TDISK	; ALREADY THERE?
	CMP	E	; MATCH IF SO
	JZ	FNDEX1
	MVI	C,14	; SELECT DISK IN E
	CALL	BDOS
FNDEX1:
	LDA	CUSER	; RESTORE CURRENT USER
	MOV	E,A	; SAVE IN E
	LDA	TUSER	; ALREADY THERE?
	CMP	E	; MATCH IF SO
	JZ	FNDEX2
	MVI	C,32	; SELECT USER IN E
	CALL	BDOS
FNDEX2:
	LDA	TDISK	; SET FOUND DISK
	MOV	B,A
	LDA	TUSER	; SET FOUND USER
	MOV	C,A
	POP	PSW	; GET RETURN CODE
	POP	D	; RESTORE REGS
	POP	H
	RET
;
;  ROUTINE TO CALL BDOS AND NOT CHANGE HL
;
BDOSH:
	PUSH	H	; CALL BDOS, BUT SAVE HL
	CALL	BDOS
	POP	H
	RET

;
;  ZFSTAT -- DETERMINE ATTRIBUTES OF FILE WHOSE FCB IS PTED TO BY DE
;	ON RETURN, B = 0 MEANS FILE IS NOT SYSTEM, C = 0 MEANS FILE IS NOT R/O
;		ZERO FLAG SET (Z) MEANS ALL OK, NZ MEANS FILE NOT FOUND
;
ZFSTAT::
	PUSH	H	; SAVE REGS
	PUSH	D
	MVI	C,17	; SEARCH FOR FILE
	CALL	BDOS
	INR	A	; SET ZERO FLAG IF NOT FOUND
	JZ	FSERR
	DCR	A	; GET OFFSET
	RRC		; CONVERT TO OFFSET INTO DMA BUFFER
	RRC
	RRC
	ANI	60H
	ADI	9	; PT TO R/O BYTE
	LHLD	DMADR	; GET CURRENT DMA ADDRESS
	ADD	L	; MAKE HL PT TO DESIRED BYTE
	MOV	L,A
	MOV	A,H
	ACI	0
	MOV	H,A
	MOV	A,M	; GET R/O BYTE
	ANI	80H	; EXTRACT BIT FLAG
	MOV	C,A	; STORE RETURN CODE IN C
	INX	H	; PT TO SYSTEM BYTE
	MOV	A,M	; GET SYSTEM BYTE
	ANI	80H	; EXTRACT BIT FLAG
	MOV	B,A	; STORE RETURN CODE IN B
	XRA	A	; ALL OK
	POP	D	; RESTORE REGS
	POP	H
	RET
FSERR:
	MVI	A,0FFH	; NOT OK -- FILE NOT FOUND
	ORA	A	; SET FLAGS
	POP	D	; RESTORE REGS
	POP	H
	RET

	END
